package cn.wonhigh.o2o.openfire.plugins;

import java.io.File;
import java.util.Collection;

import org.jivesoftware.openfire.MessageRouter;
import org.jivesoftware.openfire.OfflineMessage;
import org.jivesoftware.openfire.OfflineMessageStore;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.user.UserManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;

/**
 * 推送离线消息
 * 
 * @author wei.ss
 * @createDate 2015-03-09
 * @version 1.0
 */
public class OfflineMsgPlugin3 implements
		PacketInterceptor, Plugin {

	private static final Logger log = LoggerFactory.getLogger(OfflineMsgPlugin3.class);

	private InterceptorManager interceptorManager;
	private OfflineMessageStore offlineMessageStore;
	private MessageRouter messageRouter;
	private UserManager userManager;
	private XMPPServer server;

	public OfflineMsgPlugin3() {
	}

	public void initializePlugin(PluginManager manager, File pluginDirectory) {
		interceptorManager = InterceptorManager.getInstance();
		interceptorManager.addInterceptor(this);

		server = XMPPServer.getInstance();
		offlineMessageStore = server.getOfflineMessageStore();
		messageRouter = server.getMessageRouter();
		userManager = server.getUserManager();

		log.info("初始化离线消息插件");
	}

	public void destroyPlugin() {
		interceptorManager.removeInterceptor(this);
	}

	/**
	 * intercept message
	 */
	@Override
	public void interceptPacket(Packet packet, Session session,
			boolean incoming, boolean processed) throws PacketRejectedException {
		
		log.info("离线消息拦截器：packet={}", packet.toXML());
		if (!(packet instanceof Presence)) {
			return;
		}
		if (incoming && !processed) {
			Presence presence = (Presence) packet;
			JID from = presence.getFrom();
			if (!presence.isAvailable() || from == null) {
				return;
			}
			String username = from.getNode();
			if (username == null || !userManager.isRegisteredUser(from)) {
				return;
			}
			this.doAction(presence, incoming, processed, session);
		}
	}

	/**
	 * <b>send offline msg from this function </b>
	 */
	private void doAction(Presence presence, boolean incoming,
			boolean processed, Session session) {
		
		if (presence.isAvailable()) {
			JID from = presence.getFrom();
			String username = from.getNode();
			try {
				synchronized (username.intern()) {
					long begin = System.currentTimeMillis();
					int count = 0;
					Collection<OfflineMessage> list = offlineMessageStore.getMessages(username, true);
					if(null != list && list.size() > 0) {
						for (OfflineMessage msg : list) {
							// 添加回执请求
							msg.addChildElement("request", "urn:xmpp:receipts");
							messageRouter.route(msg);
							if (msg.getBody() != null) {
								count++;
							}
						}
					}
					log.info("处理离线消息话费时间：{}s",
							(System.currentTimeMillis() - begin) / 1000);
					log.info("用户（{}）状态在线，取得离线消息{}条", username, count);
				}
			} catch (Exception e) {
				log.error("获取用户离线消息发生异常", e);
			} 
		} else {
			try {
				session.close();
			} catch (Exception e) {
				log.warn("警告：用户脱机，关闭用户会话", e);
			}
		}
	}
}
